package pl.cezary.butler.walili.server;

import pl.cezary.butler.walili.common.TaskStatus;
import pl.cezary.butler.walili.common.Task;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.BlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;

// <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
// #[regen=yes,id=DCE.58B11F0D-06D7-219F-E065-853041FEA83C]
// </editor-fold> 
public class FetchedTasksRegisteringThread extends Thread {

    private static final Logger log = Logger.getLogger(FetchedTasksRegisteringThread.class.getName());
    private final Queues kolejki;
    private final TaskSet zadania;
    private final AbbandonedTasksProcessingTask thPorzucone;
    private final Timer timer;
    public static final int DELAY = 1 * 60;

    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.96165821-F022-5B0C-2F5B-6AF9DEC41949]
    // </editor-fold> 
    public FetchedTasksRegisteringThread(Queues k) {
        super(FetchedTasksRegisteringThread.class.getSimpleName());
        kolejki = k;
        zadania = k.getTaskStorage();
        thPorzucone = new AbbandonedTasksProcessingTask();
        timer = new Timer("Watek obslugi zadan porzuconych");
        long delay = DELAY * 20000;
        timer.scheduleAtFixedRate(thPorzucone, delay, delay);
    }

    private void zarejestrujPobranieZadania(UserTask pair) {
        ServerTask zad = pair.getZadanie();
        thPorzucone.register(zad);
    }

    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.A0F1F45A-3403-5E17-5205-8CF0A19BA6DB]
    // </editor-fold> 
    @Override
    public void run() {
        BlockingQueue<UserTask> q = kolejki.getFetchedTasksToRegisterQueue();
        try {
            while (!interrupted()) {
                zarejestrujPobranieZadania(q.take());
            }
        } catch (InterruptedException e) {
            log.log(Level.FINE,"Przerwano pracę wątku {0}",getName());
        } finally{
            timer.cancel();
        }
    }

    private class AbbandonedTasksProcessingTask extends TimerTask {
        
        private TaskSet okno = null;
        private TaskSet old = null;
        private TaskSet elder = null;

        AbbandonedTasksProcessingTask() {
            okno = new TaskSet();
            old = new TaskSet();
        }

        void register(Task zad) {
            okno.add(zad);
        }

        @Override
        public synchronized void run() {
            long start = System.currentTimeMillis();
            log.fine("Rozpoczecie przywracania zadan");
            BlockingQueue<DelayedServerTask> q = kolejki.getTasksToRevalidateQueue();
            elder = old;
            old = okno;
            okno = new TaskSet();
            int i=0;
            for (Task zad : elder) {
                if (zadania.contains(zad)) {
                    zadania.remove(zad); //FIXME CBU Co z zadaniami w toku, moze to wgole nie potrzebne
                    zad.setStatus(TaskStatus.PRZERWANE);
                    q.offer(new DelayedServerTask(zad, 0));
                    ++i;
                }
            }
            //System.gc();
            log.log(Level.INFO,"Zakonczenie przywracania {1} zadan po {0} ms", new Object[]{System.currentTimeMillis() - start, i});
        }
    }
}
